#include "iConfig.hpp"

#include <glf/io/memoryStream.h>
#include <glf/io/fileStream.h>

#include <glf/core/mem.h>

namespace glf {

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

MemoryStream::MemoryStream() :
	  IOStream()
	, mIsOwner(false)
	, mBuffer(0)
{
}

MemoryStream::MemoryStream(void* buffer, size_t size, bool isOwner) :
	IOStream()
	, mIsOwner(false)
	, mBuffer(0)
{
	Open(buffer, size, isOwner);
}

MemoryStream::MemoryStream(FileStream& file) :
	  IOStream()
	, mIsOwner(false)
	, mBuffer(0)
{
	LoadFileStream( file );
}


MemoryStream::~MemoryStream() {
	Close();
}


void MemoryStream::LoadFileStream(FileStream& file) {
	if( file.IsOpened() && file.CanRead() ) {
		size_t size = file.GetSize();
		if( size > 0 ) {
			char* buffer = new char[size];
			Open( buffer, size, true);
			//mBuffer is now equals to buffer and is init.
			file.Read( mBuffer, size );
		}
	}
}

bool MemoryStream::Open(void* buffer, size_t size, bool isOwner) {
	MemoryStream::Close();
	
	mIsOwner = isOwner;
	mBuffer = static_cast<char*>(buffer);
	mFilePosition.SetFileSize(size);

	mIsOpened = true;

	return buffer != 0;
}

void MemoryStream::Close() {
	if( mIsOwner && mBuffer) {
		delete [] mBuffer;
		mIsOwner = false;
	}
	mBuffer = 0;
	mFilePosition.Seek(0, beg);
	mFilePosition.SetFileSize(0);
	mIsOpened = false;
}

size_t MemoryStream::GetSize() const {
	return mFilePosition.GetFileSize();
}

bool MemoryStream::CanSeek() const {
	return true;
}

bool MemoryStream::CanCancel() const {
	return false;
}

bool MemoryStream::CanRead() const {
	return true;
}

bool MemoryStream::CanWrite() const {
	return false;
}

size_t MemoryStream::Tell()  const {
	return mFilePosition.Tell();
}

bool MemoryStream::Seek(int offset, seek origin) {
	return mFilePosition.Seek(offset, origin);
}

size_t MemoryStream::Read(void* buffer, size_t size)  {
    GLFi_ASSERT(buffer);
	GLFi_ASSERT(IsOpened());

	int tocopy = Min(size, mFilePosition.GetFileSize() - mFilePosition.Tell());

	Memcpy(buffer, mBuffer+mFilePosition.Tell(), tocopy);

	mFilePosition.Skip(tocopy);

	return tocopy;
}

size_t MemoryStream::Write(const void* buffer, size_t size)  {
	GLFi_ASSERT(buffer);

	size_t curPos = mFilePosition.Tell();
	size_t tocopy = Min(size, mFilePosition.GetFileSize() - curPos);
	
	Memcpy(mBuffer + curPos, buffer, tocopy);

	mFilePosition.Skip(tocopy);

	return tocopy;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

} //namespace glf

